
'use strict';

var async = require('async');
var nconf = require('nconf');

var user = require('../user');
var utils = require('../../public/src/utils');
var translator = require('../../public/src/modules/translator');
var plugins = require('../plugins');
var db = require('../database');
var meta = require('../meta');
var emailer = require('../emailer');

(function (UserEmail) {
	UserEmail.exists = function (email, callback) {
		user.getUidByEmail(email.toLowerCase(), function (err, exists) {
			callback(err, !!exists);
		});
	};

	UserEmail.available = function (email, callback) {
		db.isSortedSetMember('email:uid', email.toLowerCase(), function (err, exists) {
			callback(err, !exists);
		});
	};

	UserEmail.sendValidationEmail = function (uid, email, callback) {
		callback = callback || function () {};
		var confirm_code = utils.generateUUID();
		var confirm_link = nconf.get('url') + '/confirm/' + confirm_code;

		var emailInterval = meta.config.hasOwnProperty('emailConfirmInterval') ? parseInt(meta.config.emailConfirmInterval, 10) : 10;

		async.waterfall([
			function (next) {
				db.get('uid:' + uid + ':confirm:email:sent', next);
			},
			function (sent, next) {
				if (sent) {
					return next(new Error('[[error:confirm-email-already-sent, ' + emailInterval + ']]'));
				}
				db.set('uid:' + uid + ':confirm:email:sent', 1, next);
			},
			function (next) {
				db.pexpireAt('uid:' + uid + ':confirm:email:sent', Date.now() + (emailInterval * 60 * 1000), next);
			},
			function (next) {
				plugins.fireHook('filter:user.verify.code', confirm_code, next);
			},
			function (_confirm_code, next) {
				confirm_code = _confirm_code;
				db.setObject('confirm:' + confirm_code, {
					email: email.toLowerCase(),
					uid: uid,
				}, next);
			},
			function (next) {
				db.expireAt('confirm:' + confirm_code, Math.floor((Date.now() / 1000) + (60 * 60 * 24)), next);
			},
			function (next) {
				user.getUserField(uid, 'username', next);
			},
			function (username, next) {
				var title = meta.config.title || meta.config.browserTitle || 'NodeBB';
				translator.translate('[[email:welcome-to, ' + title + ']]', meta.config.defaultLang, function (subject) {
					var data = {
						site_title: title,
						username: username,
						confirm_link: confirm_link,
						confirm_code: confirm_code,

						subject: subject,
						template: 'welcome',
						uid: uid,
					};

					if (plugins.hasListeners('action:user.verify')) {
						plugins.fireHook('action:user.verify', { uid: uid, data: data });
						next();
					} else {
						emailer.send('welcome', uid, data, next);
					}
				});
			},
			function (next) {
				next(null, confirm_code);
			},
		], callback);
	};

	UserEmail.confirm = function (code, callback) {
		async.waterfall([
			function (next) {
				db.getObject('confirm:' + code, next);
			},
			function (confirmObj, next) {
				if (!confirmObj || !confirmObj.uid || !confirmObj.email) {
					return next(new Error('[[error:invalid-data]]'));
				}
				async.series([
					async.apply(user.setUserField, confirmObj.uid, 'email:confirmed', 1),
					async.apply(db.delete, 'confirm:' + code),
					async.apply(db.delete, 'uid:' + confirmObj.uid + ':confirm:email:sent'),
					function (next) {
						db.sortedSetRemove('users:notvalidated', confirmObj.uid, next);
					},
					function (next) {
						plugins.fireHook('action:user.email.confirmed', { uid: confirmObj.uid, email: confirmObj.email }, next);
					},
				], next);
			},
		], function (err) {
			callback(err);
		});
	};
}(exports));
